package cn.com.nes.site.service.project.impl;

import cn.com.nes.common.em.DictTypeEnum;
import cn.com.nes.mybatis.agent.crm.entity.Opportunity;
import cn.com.nes.mybatis.agent.project.entity.ProjectCustomerRelationship;
import cn.com.nes.mybatis.agent.project.entity.TProject;
import cn.com.nes.site.entity.dto.product.DeviceModelDTO;
import cn.com.nes.site.entity.em.crm.customer.CustomerLevelEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerNatureEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerSaveTypeEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityStageEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityTypeEnum;
import cn.com.nes.site.entity.iot.CascadeCell;
import cn.com.nes.site.entity.iot.NameCascade;
import cn.com.nes.site.entity.vo.crm.ExportArchivesTemplateVO;
import cn.com.nes.site.entity.vo.crm.SaveCustomerVo;
import cn.com.nes.site.entity.vo.project.ImportGovernmentalCustomerArchiveVO;
import cn.com.nes.site.modules.opportuntiy.OpportunityBusiness;
import cn.com.nes.site.service.crm.customer.CrmCustomerService;
import cn.com.nes.site.service.crm.customer.bo.SaveOpportunityBO;
import cn.com.nes.site.service.crm.customer.dto.CustomerDTO;
import cn.com.nes.site.service.crm.opportunity.CrmOpportunityService;
import cn.com.nes.site.service.product.GGoodsService;
import cn.com.nes.site.service.product.ProductSeriesAndEnergyService;
import cn.com.nes.site.service.project.GovernmentalProjectManageService;
import cn.com.nes.site.service.project.ProjectCustomerRelationshipService;
import cn.com.nes.site.service.project.TProjectService;
import cn.com.nes.site.service.project.dto.TProjectDTO;
import cn.com.nes.site.service.system.dict.TParamService;
import cn.com.nes.site.service.system.region.XzqhService;
import cn.com.nes.site.service.system.region.dto.XzqhDTO;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 政府项目管理服务实现
 */
@Service
@Slf4j
public class GovernmentalProjectManageServiceImpl implements GovernmentalProjectManageService {

    private static final int MAX_ROW = 1000;    // 每页下拉框最大行数

    private static final int MAX_YEAR = 50;     // 距今最大年限

    @Resource
    private XzqhService xzqhService;

    @Resource
    private CrmCustomerService crmCustomerService;

    @Resource
    private CrmOpportunityService crmOpportunityService;

    @Resource
    private OpportunityBusiness opportunityBusiness;

    @Resource
    private GGoodsService gGoodsService;

    @Resource
    private TProjectService tProjectService;

    @Resource
    ProjectCustomerRelationshipService projectCustomerRelationshipService;

    @Resource
    private TParamService tParamService;

    @Resource
    private ProductSeriesAndEnergyService productSeriesAndEnergyService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveMasterCustomerInfo(ImportGovernmentalCustomerArchiveVO vo) throws Exception {
        // 查询项目明细,获取客户id和商机id
        TProject project = tProjectService.getProjectDetail(vo.getProjectId());
        if (ObjectUtil.isNull(project)) {
            throw new Exception("项目信息不存在,导入失败!");
        }
        // 复制项目信息
        TProjectDTO projectDTO = new TProjectDTO();
        BeanUtils.copyProperties(project, projectDTO);
        // 设置参数
        vo.setProjectDTO(projectDTO);
        vo.setProjectUuid(project.getUuid());
        vo.setProjectName(project.getProjectName());

        // 生成政府大客户信息
        boolean updateProject = false;
        String masterCustomerId = project.getCustomerUuid();
        if (StrUtil.isBlank(masterCustomerId)) {
            masterCustomerId = saveGovernmentalCustomer(vo, project);
            updateProject = true;
            log.info("导入客户名单，生成主客户... {}", masterCustomerId);
        }
        vo.setMasterCustomerId(masterCustomerId);
        // 生成商机信息
        String opportunityId = "";
        if (StrUtil.isBlank(project.getOpportunityUuid())) {
            opportunityId = saveOpportunityInfo(vo, project);
            vo.setOpportunityId(opportunityId);
            updateProject = true;
            log.info("导入客户名单，生成主客户商机... {}", opportunityId);
        }else{
            opportunityId=project.getOpportunityUuid();
        }

        // 更新政府项目的客户信息和商机信息
        if (updateProject) {
            if (StrUtil.isNotBlank(masterCustomerId)) project.setCustomerUuid(masterCustomerId);
            if (StrUtil.isNotBlank(opportunityId)) project.setOpportunityUuid(opportunityId);
            project.setModifyuid(vo.getOperateUserId());
            project.setModifytime(vo.getOperateDate());
            log.info("导入客户名单，更新项目信息 -> {}", project);
            tProjectService.updateById(project);
        }

        // 保存项目客户关系表
        ProjectCustomerRelationship existRelationship = projectCustomerRelationshipService.hasMainCustomer(project.getUuid());
        if (ObjectUtil.isNull(existRelationship)) {
            ProjectCustomerRelationship projectCustomerRelationship = new ProjectCustomerRelationship();
            projectCustomerRelationship.setCustomerId(masterCustomerId);
            projectCustomerRelationship.setBusinessId(opportunityId);
            projectCustomerRelationship.setMainBusinessId(opportunityId);
            projectCustomerRelationship.setMainCustomerId(masterCustomerId);
            projectCustomerRelationship.setProjectUuid(project.getUuid());
            projectCustomerRelationship.setMainFlag(1);
            projectCustomerRelationship.setImportBatch(vo.getOperateTimeStamp());
            projectCustomerRelationship.setDataType(1);
            projectCustomerRelationship.setDeleted(0);
            projectCustomerRelationship.setGmtCreateId(vo.getOperateUserId());
            projectCustomerRelationship.setGmtCreate(vo.getOperateDate());
            projectCustomerRelationshipService.save(projectCustomerRelationship);
        }
         return opportunityId;
    }

    @Override
    public List<CascadeCell> getExportInfo(ExportArchivesTemplateVO vo) throws Exception {
        List<CascadeCell> cascadeCellList = new ArrayList<>();
        cascadeCellList.add(getAreaNameConfig(vo));         // 行政区划
        cascadeCellList.add(getBuildingStructureConfig());  // 建筑结构
        cascadeCellList.add(getHouseTypeConfig());          // 房屋类型
        cascadeCellList.add(getHeatingEndConfig());         // 采暖末端
        cascadeCellList.add(getPlayYearConfig());           // 计划年度
        cascadeCellList.add(getEnergyTypeConfig());         // 能源类型
        cascadeCellList.add(getHeatingTypeNameConfig());    // 供暖方式
        cascadeCellList.add(getEquipmentModelConfig(vo));   // 设备型号
        cascadeCellList.add(getTrueOrFalseConfig());        // 是否本村户籍
        return cascadeCellList;
    }

    // 保存政府大客户信息
    private String saveGovernmentalCustomer(ImportGovernmentalCustomerArchiveVO vo, TProject project) throws Exception {
        try {
            SaveCustomerVo saveCustomerVo = new SaveCustomerVo();
            BeanUtils.copyProperties(vo, saveCustomerVo);
            saveCustomerVo.setCustomerName(vo.getContactName());
            saveCustomerVo.setContact(vo.getContactName());
            saveCustomerVo.setPhone(vo.getContactPhone());
            saveCustomerVo.setCustomerNature(CustomerNatureEnum._government.getKey()); // 政府客户
            saveCustomerVo.setCustomerLevel(CustomerLevelEnum._level_1.getType());
            saveCustomerVo.setSaveType(Integer.valueOf(CustomerSaveTypeEnum._my.getType()));
            saveCustomerVo.setMemo("[" + vo.getProjectName() + "] 项目导入的政府类别客户");
            saveCustomerVo.setAddress(project.getProjectAddress());

            CustomerDTO customerDTO = crmCustomerService.saveCrmCustomer(saveCustomerVo);
            log.info("政府项目名单导入 -> 新增政府类别客户... [{}]", customerDTO.getUuid());
            return customerDTO.getUuid();
        } catch (Exception e) {
            log.error("保存客户基本信息失败,客户姓名:{},客户电话号:{},异常原因:{}", vo.getContactName(), vo.getContactPhone(), e.getMessage());
            throw e;
        }
    }

    // 保存商机信息
    public String saveOpportunityInfo(ImportGovernmentalCustomerArchiveVO vo, TProject project) throws Exception {
        try {
            SaveOpportunityBO saveOpportunityBO = new SaveOpportunityBO();
            BeanUtils.copyProperties(vo, saveOpportunityBO);
            saveOpportunityBO.setOpportunityStage(OpportunityStageEnum._transaction); // 默认商机成交
            saveOpportunityBO.setOpportunityType(OpportunityTypeEnum._purchase); // 默认购买设备
            saveOpportunityBO.setOpportunityName(vo.getProjectDTO().getProjectName() + "_导入生成商机");
            saveOpportunityBO.setCustomerId(vo.getMasterCustomerId());
            saveOpportunityBO.setXzqhdm(vo.getProjectDTO().getAreaCode());
            saveOpportunityBO.setProjectAddress(vo.getProjectDTO().getProjectAddress());
            saveOpportunityBO.setPersonInCharge(vo.getContactName());
            saveOpportunityBO.setPersonInChargePhone(vo.getContactPhone());
            saveOpportunityBO.setMemo("导入生成商机");
            saveOpportunityBO.setEstimatedClosingDate(vo.getOperateDate());
            saveOpportunityBO.setBuildNature("改造");
            saveOpportunityBO.setCgfType("总承包");
            saveOpportunityBO.setCjfCompanyName(vo.getUserInfo().getCompanyName());
            saveOpportunityBO.setLongitude(vo.getProjectDTO().getLongitude());
            saveOpportunityBO.setLatitude(vo.getProjectDTO().getLatitude());
            saveOpportunityBO.setProjectAddress(project.getProjectAddress());
            Opportunity opportunity = opportunityBusiness.save(saveOpportunityBO.convertToBO());
            log.info("政府项目名单导入 -> 新增政府类别客户的商机... [{}]", opportunity.getUuid());
            return opportunity.getUuid();
        } catch (Exception e) {
            log.error("保存商机信息失败,客户姓名:{},客户电话号:{},异常原因:{}", vo.getContactName(), vo.getContactPhone(), e.getMessage());
            throw new Exception();
        }
    }

    // 获取导出模板行政区划名称下拉框列表
    private CascadeCell getAreaNameConfig(ExportArchivesTemplateVO vo) throws Exception {
        List<XzqhDTO> xzqhDTOList = xzqhService.getXzqhListByXzqhdmList(vo.getXzqhdmList());
        if (CollectionUtil.isEmpty(xzqhDTOList)) {
            throw new Exception("行政区划为空,模板下载失败!");
        }
        List<NameCascade> nameCascadeList = new ArrayList<>();
        getChildList(xzqhDTOList, nameCascadeList);

        CascadeCell cascadeCell = new CascadeCell();
        cascadeCell.setRowIndex(2);
        cascadeCell.setColumnIndex(0);
        cascadeCell.setRowNum(MAX_ROW);
        cascadeCell.setNameCascadeList(nameCascadeList.stream().distinct().collect(Collectors.toList()));
        return cascadeCell;
    }

    // 获取行政区划编码名称
    private void getChildList(List<XzqhDTO> xzqhDTOList, List<NameCascade> nameCascadeList) {
        for (XzqhDTO item : xzqhDTOList) {
            if (!"5".equals(item.getXzqhjb())) {
                getXzqhName(item.getChildList(), nameCascadeList);
            } else {
                NameCascade nameCascade = new NameCascade();
                nameCascade.setName(item.getXzqhdm() + "_" + item.getXzqhmc());
              /*  nameCascade.setName(item.getXzqhmc());*/
                nameCascadeList.add(nameCascade);
            }
        }
    }
    private void getXzqhName(List<XzqhDTO> xzqhDTOList, List<NameCascade> nameCascadeList) {
        for (XzqhDTO item : xzqhDTOList) {
            NameCascade nameCascade = new NameCascade();
           nameCascade.setName(item.getXzqhdm() + "_" + item.getXzqhmc());
           /* nameCascade.setName(item.getXzqhmc());*/
            nameCascadeList.add(nameCascade);
        }
    }

    // 建筑结构
    private CascadeCell getBuildingStructureConfig() throws Exception {
        List<Map<String, String>> configTemplate = tParamService.getListMap(DictTypeEnum.BUILDING_STRUCTURE.getParamType());
        return assembleConfig(configTemplate, 7);
    }

    // 房屋类型
    private CascadeCell getHouseTypeConfig() throws Exception {
        List<Map<String, String>> configTemplate = tParamService.getListMap(DictTypeEnum.HOUSE_TYPE.getParamType());
        return assembleConfig(configTemplate, 8);
    }

    // 采暖末端
    private CascadeCell getHeatingEndConfig() throws Exception {
        List<Map<String, String>> configTemplate = tParamService.getListMap(DictTypeEnum.HEATING_END.getParamType());
        return assembleConfig(configTemplate, 9);
    }

    // 计划年度
    private CascadeCell getPlayYearConfig() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);

        List<NameCascade> nameCascadeList = new ArrayList<>();
        for (int i = 0; i < MAX_YEAR; i++) {
            NameCascade nameCascade = new NameCascade();
            nameCascade.setName((year + i) + "");
            nameCascadeList.add(nameCascade);
        }

        CascadeCell cascadeCell = new CascadeCell();
        cascadeCell.setRowIndex(2);
        cascadeCell.setColumnIndex(10);
        cascadeCell.setRowNum(MAX_ROW);
        cascadeCell.setNameCascadeList(nameCascadeList);
        return cascadeCell;
    }

    // 能源类型
    private CascadeCell getEnergyTypeConfig() throws Exception {
        List<Map<String, String>> configTemplate = tParamService.getListMap(DictTypeEnum.ENERGY_TYPE.getParamType());
        return assembleConfig(configTemplate, 11);
    }

    // 供暖方式
    private CascadeCell getHeatingTypeNameConfig() throws Exception {
        List<Map<String, String>> configTemplate = tParamService.getListMap(DictTypeEnum.HEATING_MODE.getParamType());
        return assembleConfig(configTemplate, 12);
    }

    // 设备类型
/*    private CascadeCell getEquipmentTypeConfig() throws Exception {
        List<Map<String, String>> configTemplate = productSeriesAndEnergyService.getSeriesConfigTemplate();
        return assembleConfig(configTemplate, 0);
    }*/

    // 设备型号
    private CascadeCell getEquipmentModelConfig(ExportArchivesTemplateVO vo) throws Exception {
        // 查询当前公司全部产品
        TProject project = tProjectService.getProjectDetail(vo.getProjectId());
        if(project==null){
            throw new Exception("公司未添加设备类型,请在创建项目时添加设备类型!");
        }
        String[] parts = project.getDeviceModels().split(";");
        List<DeviceModelDTO>deviceModeList = gGoodsService.getDeviceModels(vo.getOperateUserCompanyId(), Arrays.asList(parts));
        if (CollectionUtil.isEmpty(deviceModeList)) {
            return null;
        }

        // 组装配置
        List<Map<String, String>> configTemplate = new ArrayList<>();
        for (DeviceModelDTO item : deviceModeList) {
            Map<String, String> map = new HashMap<>();
            map.put("value", item.getDeviceModel());
            map.put("name", item.getDeviceModelName());
            configTemplate.add(map);
        }
        return assembleConfig(configTemplate, 13);
    }

    // 是否本村户籍
    private CascadeCell getTrueOrFalseConfig() {
        // 配置选项
        Map<String, String> map_1 = new HashMap<>();
        map_1.put("value", "0");
        map_1.put("name", "否");

        Map<String, String> map_2 = new HashMap<>();
        map_2.put("value", "1");
        map_2.put("name", "是");

        List<Map<String, String>> configTemplate = new ArrayList<>();
        configTemplate.add(map_1);
        configTemplate.add(map_2);
        return assembleConfig(configTemplate, 14);
    }

    // 组装配置
    private CascadeCell assembleConfig(List<Map<String, String>> configTemplate, Integer columnIndex) {
        // 组装选项
        List<NameCascade> nameCascadeList = new ArrayList<>();
        for (Map<String, String> item : configTemplate) {
            NameCascade nameCascade = new NameCascade();
           /* nameCascade.setName(item.get("name"));*/
            nameCascade.setName(item.get("value") + "_" + item.get("name"));
            nameCascadeList.add(nameCascade);
        }
        // 组装配置
        CascadeCell cascadeCell = new CascadeCell();
        cascadeCell.setRowIndex(2);
        cascadeCell.setColumnIndex(columnIndex);
        cascadeCell.setRowNum(MAX_ROW);
        cascadeCell.setNameCascadeList(nameCascadeList);
        return cascadeCell;
    }
}
